package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDataPageReqDto;
import com.zzyl.entity.Device;
import com.zzyl.entity.DeviceData;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceDataMapper;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.runner.IotContent;
import com.zzyl.service.DeviceDataService;
import com.zzyl.vo.DeviceDataVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
public class DeviceDataServiceImpl implements DeviceDataService {
    @Autowired
    private DeviceDataMapper deviceDataMapper;
    @Autowired
    private DeviceMapper  deviceMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 解析IOT平台推送的设备上报信息，,并保存到数据库中
     */
    @Override
    public void processIotMessage(String content) {
        if(StrUtil.isEmpty(content)){
            return;
        }
        //1. 将设备上报的JSON数据, 转化为Java对象
        IotContent iotContent = JSONUtil.toBean(content, IotContent.class);
        // 查询设备详情
        String iotId = iotContent.getIotId();
        Device device=deviceMapper.queryByIotId(iotId);
        if (Objects.isNull(device)) {
            return;
        }
        //2. 获取设备上报的指标数据, 封装对象
        Map<String, IotContent.Item> items = iotContent.getItems();
        if (CollectionUtil.isEmpty(items)) {
            return;
        }
        //3. 保存数据到数据库
        ArrayList<Object> deviceDataList = new ArrayList<>();
        items.forEach((key, item) -> {
            DeviceData deviceData = new DeviceData();
            deviceData.setDeviceName(iotContent.getDeviceName());
            deviceData.setIotId(iotId);
            deviceData.setNickname(device.getNickname());
            deviceData.setProductKey(iotContent.getProductKey());
            deviceData.setProductName(device.getProductName());
            deviceData.setFunctionId(key);
            deviceData.setAccessLocation(device.getBindingLocation());
            deviceData.setPhysicalLocationType(device.getPhysicalLocationType());
            deviceData.setDeviceDescription(device.getDeviceDescription());
            deviceData.setDataValue(item.getValue()+"");
            deviceData.setAlarmTime(LocalDateTimeUtil.of(item.getTime()));
            deviceData.setLocationType(device.getLocationType());
            deviceDataList.add(deviceData);
        });
        // 将设备上报的最新数据保存到 Redis  String hash set zset list
        // 存储到Redis之后, 能够方便的从Redis中获取设备数据
        // String   Key : 前缀+设备id   value:上报的最新数据
        // hash     Key : 固定的集合名称     hashKey : 设备id    vlaue : 上报的最新数据
        List<DeviceDataVo> deviceDataVos = BeanUtil.copyToList(deviceDataList, DeviceDataVo.class);
        redisTemplate.opsForHash().put(CacheConstants.IOT_DEVICE_LAST_DATA,iotContent.getIotId(),JSONUtil.toJsonStr(deviceDataVos));
        // 最后再把设备上报的最新消息，保存到数据
        deviceDataMapper.insertBatch(deviceDataList);
    }

    /**
     * 分页查询智能设备运行数据列表
     */
    @Override
    public PageResponse<DeviceDataVo> dataList(DeviceDataPageReqDto deviceDataPageReqDto) {
        //1. 处理请求参数
        String deviceName = deviceDataPageReqDto.getDeviceName();
        if (StrUtil.isEmpty(deviceName)) {
            throw new BaseException(BasicEnum.PARAMETER_MISSING);
        }
        String functionId = deviceDataPageReqDto.getFunctionId();
        if (StrUtil.isEmpty(functionId)) {
            throw new BaseException(BasicEnum.PARAMETER_MISSING);
        }
        //开始时间处理  : 默认时间当前时间-1小时
        Long startTime = deviceDataPageReqDto.getStartTime();
        LocalDateTime startDate = startTime == null ? LocalDateTimeUtil.offset(LocalDateTime.now(), -1, ChronoUnit.HOURS) : LocalDateTimeUtil.of(startTime);
        //结束时间处理  : 默认时间当前时间
        Long endTime = deviceDataPageReqDto.getEndTime();
        LocalDateTime endDate = endTime == null ? LocalDateTime.now() : LocalDateTimeUtil.of(endTime);
        //2. 开启分页
        PageHelper.startPage(deviceDataPageReqDto.getPageNum(), deviceDataPageReqDto.getPageSize());
        //3. 查询数据列表
        Page<DeviceData> page = deviceDataMapper.dataList(deviceName,functionId,startDate,endDate);
        //4. 封装数据返回
        return PageResponse.of(page,DeviceDataVo.class);
    }
}
